#include "graphics.h"

#include <stdio.h>
#include <assert.h>


unsigned int const VERTEXES_PER_CIRCLE = 40;


void sdl_setup(int width, int height, SDL_Window ** window,
		SDL_Renderer ** renderer) {
	*window = NULL;
	*renderer = NULL;
	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		printf("SDL initialization failed. Error: %s\n", SDL_GetError());
		return;
	}
	
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
			SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	*window = SDL_CreateWindow("Droplets", SDL_WINDOWPOS_UNDEFINED,
			SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
	if (*window == NULL) {
		printf("Window creation failed. Error: %s\n", SDL_GetError());
	}
	else {
		*renderer = SDL_CreateRenderer(*window, -1, 0);
		if (*renderer == NULL) {
			printf("Renderer creation failed. Error: %s\n", SDL_GetError());
			SDL_DestroyWindow(*window);
			*window = NULL;
		}
	}
}


void gl_setup(SDL_GLContext * gl_context, SDL_Window * window) {
	*gl_context = SDL_GL_CreateContext(window);
	assert(*gl_context != NULL);
	glewExperimental = true;
    GLenum glew_err = glewInit();
    assert(glew_err == GLEW_OK);
}


void graphics_finish(
		SDL_Window * window,
		SDL_Renderer * renderer,
		SDL_GLContext * gl_context) {
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_GL_DeleteContext(gl_context);
	renderer = NULL;
	window = NULL;
	gl_context = NULL;
	SDL_Quit();
}


bool sdl_quit() {
	SDL_Event e;
	SDL_PollEvent(&e);
	if (e.type == SDL_QUIT) {
		return true;
	}
	return false;
}


void create_circles(GLfloat * vertexes, Droplet * circles, size_t circles_count,
		float screen_width, float screen_height) {
	/*
	Draws the given circles.
	
	Args:
		[out] vertexes: 1D array of length
			`circles_count * VERTEXES_PER_CIRCLE * 3`. This is where the
			coordinates of each circle will be stored, where each vertex has 3
			coordinates
		[in] circles: array of Droplet objects to draw
		[in] circles_count: number of objects in `circles`
		[in] screen_width: width of the screen
		[in] screen_height: height of the screen
	*/
	float const rotation_step = (2.0 * M_PI) / VERTEXES_PER_CIRCLE;
	// Unit vector of the current rotation
	GLfloat x = 0.0;
	GLfloat y = 1.0;
	// Calculate the coordinates of each circles vertexes
	for (unsigned int i=0; i<VERTEXES_PER_CIRCLE; i++) {
		for (	unsigned int circle_idx = 0;
				circle_idx < circles_count;
				circle_idx++) {
			size_t vertex_idx = circle_idx * VERTEXES_PER_CIRCLE * 3 + i * 3;
			GLfloat x_scaled = x * circles[circle_idx].radius;
			GLfloat y_scaled = y * circles[circle_idx].radius;
			vertexes[vertex_idx] = (
					(x_scaled + circles[circle_idx].x)
					/ screen_width * 2.0 - 1.0 );
			vertexes[vertex_idx + 1] = -1.0 * (
					(y_scaled + circles[circle_idx].y)
					/ screen_height * 2.0 - 1.0 );
			vertexes[vertex_idx + 2] = 0;
		}
		
		float tmp_x = x;
		x = tmp_x * cosf(rotation_step) - y * sinf(rotation_step);
		y = tmp_x * sinf(rotation_step) + y * cosf(rotation_step);
	}
}
